<!--
 * @Author: wangming
 * @Date: 2021-05-12 16:36:21
 * @LastEditors: wangming
 * @LastEditTime: 2022-06-01 11:52:22
 * @Description: file content
-->
<template>
  <el-drawer
    :visible="drawer"
    direction="btt"
    :with-header="false"
    :modal="false"
    :close-on-press-escape="false"
    :wrapperClosable="false"
    :size="drawerHeight"
  >
    <div ref="DraggableBottom" class="draggable-sider">
      <div class="draggable-sider__content">
        <div class="editor__btns">
          <div title="帮助中心" class="editor__btn" @click.stop="goHelp">
            <IconPark size="18" type="help" fill="#666" />
          </div>
          <div title="最大化" class="editor__btn" @click.stop="openFreeEditor">
            <IconPark type="full-screen-two" size="18" fill="#666" />
          </div>
          <div title="关闭" class="editor__btn" @click.stop="closed">
            <IconPark type="close" size="18" fill="#666" />
          </div>
        </div>
        <el-tabs class="editor__tabs" type="card" v-model="activeName">
          <el-tab-pane label="页面js" name="javascript">
            <div id="monacojs" class="editor__monaco"></div>
          </el-tab-pane>
          <el-tab-pane label="页面css" name="css">
            <div id="monacocss" class="editor__monaco"></div>
          </el-tab-pane>
        </el-tabs>
      </div>
      <div
        id="dragHandler"
        class="border-handler"
        @mousedown.stop.prevent="onMouseDown"
      ></div>
    </div>
  </el-drawer>
</template>

<script>
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
import FreeEditor from "@/utils/freeEditor.js";
import store from "@/store";
import { IconPark } from "@icon-park/vue/es/all";
import MonacoEditorHint from "@/hint/monacoeditor";
MonacoEditorHint.init("javascript", "FreeEditor");
let currentH = 0;
let currentHeight = 0;
export default {
  data() {
    return {
      drawer: false,
      drawerHeight: "40%",
      activeName: "",
      monacojs: null,
      monacocss: null,
      jsData: "",
      cssData: "",
      formData: {
        js: "",
        css: "",
        key: "",
      },

      dragging: false,
      calcMinHeight: 0,
      maxHeight: "none",
      minHeight: 300,
      height: 0,
    };
  },
  components: {
    IconPark,
  },
  computed: {
    system() {
      return /macintosh|mac os x/i.test(navigator.userAgent.toLowerCase());
    },
  },
  destroyed() {
    if (this.monacojs) {
      this.monacojs.dispose();
    }
    if (this.monacocss) {
      this.monacocss.dispose();
    }
  },
  mounted() {
    this.maxHeight = document.documentElement.clientHeight;
  },
  watch: {
    async activeName(v) {
      if (!this.monacocss && v === "css") {
        this.showcss();
      }
      if (!this.monacojs && v === "javascript") {
        this.showjs();
      }
    },
    async drawer(v) {
      if (v) {
        await this.$nextTick();
        this.onOpenDrawer();
        document.documentElement.addEventListener("keydown", this.saveContent);
      } else {
        document.documentElement.removeEventListener(
          "mousemove",
          this.onMouseMove
        );
        document.documentElement.removeEventListener("mouseup", this.onMouseUp);
        document.documentElement.removeEventListener(
          "keydown",
          this.saveContent
        );
      }
    },
  },

  methods: {
    saveContent(e) {
      var key = window.event.keyCode
        ? window.event.keyCode
        : window.event.which;
      if (key === 83 && e.ctrlKey) {
        e.preventDefault();
        this.closed();
      }
    },
    onOpenDrawer() {
      document.documentElement.addEventListener("mousemove", this.onMouseMove);
      document.documentElement.addEventListener("mouseup", this.onMouseUp);
      const parentNode = this.$refs.DraggableBottom.parentNode;
      this.calcMinHeight = this.height = parseInt(parentNode.offsetHeight);
    },
    onMouseDown(e) {
      this.dragging = true;
      currentH = e.clientY;
      currentHeight = parseInt(this.height);
    },
    onMouseMove(e) {
      if (!this.dragging) return;
      const deltaH = e.clientY - currentH;
      let finalHeight = 0;
      finalHeight = currentHeight - deltaH;
      this.height = Math.min(
        Math.max(finalHeight, parseInt(this.minHeight)),
        this.maxHeight
      );
      this.drawerHeight = this.height;
    },
    onMouseUp(e) {
      if (this.dragging) {
        this.dragging = false;
        this.drawerHeight = this.height;
        this.afterMouseUp();
      }
    },
    afterMouseUp() {
      if (this.monacojs) {
        this.jsData = this.monacojs.getValue() + "";
        this.monacojs.dispose();
        this.monacojs = null;
      }
      if (this.monacocss) {
        this.cssData = this.monacocss.getValue() + "";
        this.monacocss.dispose();
        this.monacocss = null;
      }
      this.callback();
      this.activeName == "javascript" ? this.showjs() : this.showcss();
    },
    goHelp() {
      window.open("https://hancode.yuque.com/ibi3kw/qzp9ku/nxzmh9");
    },
    initEditorContent() {
      // 初始化编辑器 当只执行openFreeEditor
      if (this.monacojs) {
        this.monacojs.dispose();
        this.monacojs = null;
      }
      if (this.monacocss) {
        this.monacocss.dispose();
        this.monacocss = null;
      }
      this.activeName = "";
    },
    saveEditor({ js, css, key }) {
      if (this.formData.key === key) {
        this.monacojs && this.monacojs.setValue(js);
        this.monacocss && this.monacocss.setValue(css);
      }
      this.callback({ js, css, key });
    },
    callback(_formData) {
      if (_formData) {
        const { key } = _formData;
        const data = store.getters.getFormDataForMain;
        const pc_key = data.key;
        const flag = data.template.find((item) => item?.FormData.key === key);
        if (pc_key === key || flag) {
          store.dispatch("UpdateFormData", _formData);
        } else {
          this.freeEditorIns.errorPostMessage();
        }
      } else {
        this.formData.js = this.jsData
          ? encodeURIComponent(this.jsData.trim())
          : "";
        this.formData.css = this.cssData;
      }
    },
    openFreeEditor() {
      this.freeEditorIns = new FreeEditor();
      this.drawer = false;
      this.formData.js = this.formData.js
        ? decodeURIComponent(this.formData.js)
        : this.monacojs && this.monacojs.getValue() + "";
      this.formData.css =
        this.formData.css || (this.monacocss && this.monacocss.getValue() + "");
      this.freeEditorIns.open({
        // ... 其他配置
        lang: "javascript",
        title: document.title,
        formData: this.formData,
        save: (formData) => {
          // formData.js = formData.js ? decodeURIComponent(formData.js) : "";
          formData.js = formData.js ? encodeURIComponent(formData.js) : "";
          this.saveEditor(formData);
        },
      });
    },
    async showEdit(language, formData) {
      await this.initEditorContent();
      this.formData = formData;
      const { js, css } = this.formData;
      this.jsData = js ? decodeURIComponent(js) : "";
      this.cssData = css;
      this.activeName = language;
      this.drawer = true;
    },
    closed() {
      const error = monaco.editor
        .getModelMarkers()
        .filter((i) => i.code !== "6133" && i.code !== "2339");
      if (error.length > 0) {
        this.$message.error("语法错误" + error[0]?.message);
        return;
      }
      if (this.monacojs) {
        this.jsData = this.monacojs.getValue() + "";
        this.monacojs.dispose();
        this.monacojs = null;
      }
      if (this.monacocss) {
        this.cssData = this.monacocss.getValue() + "";
        this.monacocss.dispose();
        this.monacocss = null;
      }
      this.callback();
      this.activeName = "";
      this.drawer = false;
    },
    async showjs() {
      await this.$nextTick();
      this.monacojs = monaco.editor.create(
        document.getElementById("monacojs"),
        {
          value: this.jsData,
          language: "javascript",
          fixedOverflowWidgets: true,
        }
      );
    },
    async showcss() {
      await this.$nextTick();
      this.monacocss = monaco.editor.create(
        document.getElementById("monacocss"),
        {
          value: this.cssData,
          language: "less",
          fixedOverflowWidgets: true,
        }
      );
    },
  },
};
</script>

<style lang="scss" scoped>
.editor__btns {
  position: absolute;
  right: 14px;
  top: 0;
  z-index: 999;
  height: 40px;
  display: flex;

  .editor__btn {
    height: 40px;
    min-width: 40px;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
  }
}

.editor__tabs {
  height: 100%;

  ::v-deep .el-tabs__content {
    height: calc(100% - 58px);
  }

  .el-tab-pane,
  .editor__monaco {
    height: 100%;
  }
}
.draggable-sider {
  position: relative;
  height: 100%;
  transition: min-height 0.2s, max-height 0.2s;

  &__content {
    height: 100%;
    overflow-y: auto;
  }

  .border-handler {
    position: absolute;
    width: 100%;
    height: 6px;
    top: 0;
    bottom: 0;
    cursor: row-resize;
  }
}
</style>
